package com.example.adminbase.mybatisgenerator;

import com.example.adminbase.service.CrudService;
import com.example.adminbase.web.CrudControllerAdapter;
import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.config.PropertyRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Collections;
import java.util.List;
import java.util.Properties;

public class ControllerGenerationPlugin extends PluginAdapter {

    private String targetProject;

    private String targetPackage;

    @Override
    public void setProperties(Properties properties) {
        super.setProperties(properties);
        targetProject = (String) properties.get("targetProject");
        targetPackage = (String) properties.get("targetPackage");
    }

    @Override
    public boolean validate(List<String> warnings) {
        return true;
    }

    @Override
    public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
        if("true".equals(introspectedTable.getTableConfigurationProperty("generateController"))) {
            return Collections.singletonList(
                    generateController(introspectedTable)
            );
        }
        return null;
    }

    private GeneratedJavaFile generateController(IntrospectedTable introspectedTable) {
        TopLevelClass controller = new TopLevelClass(targetPackage + "." +
                introspectedTable.getFullyQualifiedTable().getDomainObjectName() + "Controller");
        Interface interfaze = (Interface) introspectedTable.getAttribute("service");
        controller.addAnnotation("@Controller");
        controller.addImportedType(Controller.class.getName());
        controller.addAnnotation("@RequestMapping(\"/" + StringUtils.uncapitalize(introspectedTable.getFullyQualifiedTable().getDomainObjectName()) + "\")");
        controller.addImportedType(RequestMapping.class.getName());

        FullyQualifiedJavaType superClass = new FullyQualifiedJavaType(CrudControllerAdapter.class.getName());
        superClass.addTypeArgument(MybatisGeneratorUtil.getIdColumn(introspectedTable).getFullyQualifiedJavaType());
        superClass.addTypeArgument(new FullyQualifiedJavaType(introspectedTable.getBaseRecordType()));
        controller.addImportedType(introspectedTable.getBaseRecordType());

        controller.setSuperClass(superClass);
        controller.addImportedType(CrudControllerAdapter.class.getName());

        Field field = MybatisGeneratorUtil.buildDeletableField("service",
                interfaze.getType());
        controller.addImportedType(interfaze.getType());
        field.setVisibility(JavaVisibility.PRIVATE);
        field.addAnnotation("@Autowired");
        controller.addImportedType(Autowired.class.getName());
        controller.addField(field);

        Method getService = MybatisGeneratorUtil.buildDeletableMethod("getService");
        getService.addAnnotation("@Override");
        FullyQualifiedJavaType returnType = new FullyQualifiedJavaType(CrudService.class.getName());
        returnType.addTypeArgument(MybatisGeneratorUtil.getIdColumn(introspectedTable).getFullyQualifiedJavaType());
        returnType.addTypeArgument(new FullyQualifiedJavaType(introspectedTable.getBaseRecordType()));
        getService.setReturnType(returnType);
        controller.addImportedType(CrudService.class.getName());
        getService.addBodyLine("return service;");
        getService.setVisibility(JavaVisibility.PUBLIC);
        controller.addMethod(getService);
        return new GeneratedJavaFile(controller,
                targetProject,
                context.getProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING),
                context.getJavaFormatter());
    }
}
